package topo;

import java.util.Random;


import util.IOTopology;

public class TopologyGenerator {

	/**
	 * 
	 * @param numHorNodes
	 * @param numVerNodes
	 * @return graph
	 * @author Remzi Celebi
	 */

	private static TopologyGenerator singleton = new TopologyGenerator();

	public static TopologyGenerator getTopoglogyGenerator() {
		return singleton;
	}

	private TopologyGenerator() {
	}

	// /pbc :periodic boundary condition

	public Topology createGrid(int numHorNodes, int numVerNodes, int pbc) {

		Topology graph = new Topology();
		graph.setLabel("GRID");

		int countX = numHorNodes;
		int countY = numVerNodes;

		Node[][] matrix = new Node[countX][countY];

		for (int i = 0; i < countX; i++) {
			for (int j = 0; j < countY; j++) {
				matrix[i][j] = new Node();
				graph.addNode(matrix[i][j]);

			}
		}
		for (int i = 0; i < countX; i++) {
			for (int j = 0; j < countY; j++) {
				if (j == 0) {
					if (pbc > 0)
						graph.addEdge(new Edge(matrix[i][countY - 1],
								matrix[i][j]));
				} else if (j > 0)
					graph.addEdge(new Edge(matrix[i][j - 1], matrix[i][j]));
			}
		}
		for (int i = 0; i < countX; i++) {
			for (int j = 0; j < countY; j++) {
				if (i == 0) {
					if (pbc > 0)
						graph.addEdge(new Edge(matrix[countX - 1][j],
								matrix[i][j]));
				} else if (i > 0)
					graph.addEdge(new Edge(matrix[i - 1][j], matrix[i][j]));
			}
		}

		return graph;
	}

	public Topology createStar(int numInnerNodes, int numOuterNodes) {
		Topology graph = new Topology();
		graph.setLabel("STAR");
		int maxConnect = numInnerNodes;

		Node center = new Node();
		graph.addNode(center);

		for (int i = 0; i < maxConnect; i++) {

			Node gn = new Node();
			graph.addNode(gn);
			graph.addEdge(new Edge(center, gn));

			for (int j = 0; i < numOuterNodes; j++) {

				Node gn2 = new Node();
				graph.addNode(gn2);
				graph.addEdge(new Edge(gn2, gn));
			}

		}

		return graph;
	}

	public Topology createRandom(int numNodes) {

		Topology graph = new Topology();
		graph.setLabel("RANDOM");

		Random rng = new Random();
		Node prev = new Node();
		graph.addNode(prev);
		for (int i = 0; i < numNodes - 1; i++) {
			Node cur = new Node();
			graph.addNode(cur);

			graph.addEdge(new Edge(prev, cur));
			prev = cur;
		}
		return graph;
	}
	public static Topology createFullConnectedGraph(int numNodes){
		Topology graph = new Topology();
		graph.setLabel("FULLCONNECTED");
		Node[] gn = new Node[numNodes];
		for(int i=0;i<numNodes;i++){
			gn[i]= new Node();
			graph.addNode(gn[i]);
		}
		for(int i=0;i<numNodes;i++){
			for(int j=i+1;j<numNodes;j++){
				graph.addEdge(new Edge(gn[i],gn[j]));
			}
		}
		return graph;
	}

	public Topology createCircle(int numNodes) {

		Topology graph = new Topology();
		graph.setLabel("CIRCLE");

		int nr = numNodes;

		Node[] gn = new Node[nr];

		for (int i = 0; i < nr; i++) {

			gn[i] = new Node();
			graph.addNode(gn[i]);

		}
		Edge[] re = new Edge[nr];

		for (int i = 0; i < nr; i++) {
			re[i] = new Edge(gn[i], gn[(i + 1) % nr]);
			graph.addEdge(re[i]);
		}

		return graph;
	}

	public static void main(String[] args) {
		TopologyGenerator topogen = TopologyGenerator.getTopoglogyGenerator();
//		Topology topo = topogen.createGrid(100, 100, 1);
		Topology topo = topogen.createFullConnectedGraph(20);
		//topo = ScaleFreeNetwork.instance().createScaleFreeNet(4, 4, 16);
		 IOTopology.exportTopologyFile(topo,"topology_100.txt");
	}

}
